{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "4Kz7WHKjT_AD"
   },
   "outputs": [],
   "source": [
    "import requests\n",
    "from bs4 import BeautifulSoup\n",
    "import threading\n",
    "import json\n",
    "from data.crawler.data_objects import Api, ApiVersion, Changelog, DeadPoolApi\n",
    "\n",
    "# Sep.16, 2020\n",
    "max_page = 948"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "mqwA0-eYULx6"
   },
   "outputs": [],
   "source": [
    "# Assist function. Split a list\n",
    "def list_split(list_info, per_list_len):\n",
    "    \"\"\"\n",
    "    :param list_info:   列表\n",
    "    :param per_list_len:  每个小列表的长度\n",
    "    :return:\n",
    "    \"\"\"\n",
    "    list_of_group = zip(*(iter(list_info),) * per_list_len)\n",
    "    end_list = [list(i) for i in list_of_group]  # i is a tuple\n",
    "    count = len(list_info) % per_list_len\n",
    "    end_list.append(list_info[-count:]) if count != 0 else end_list\n",
    "    return end_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "6iB4vQoJcusX"
   },
   "outputs": [],
   "source": [
    "pages = [i for i in range(max_page)]\n",
    "pages_split = list_split(pages, 8)    # Split the pages for multi-threads work\n",
    "pages_split     # preview"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "LU6czcqCU0hq"
   },
   "outputs": [],
   "source": [
    "# Save the URLs for future works.\n",
    "base = 'https://www.programmableweb.com/category/all/apis?deadpool=1&page='\n",
    "api_links = {}\n",
    "failed_page_idx = []    # save the page number when no table is found\n",
    "\n",
    "\n",
    "def get_list(thread_count, pages):\n",
    "    \"\"\"\n",
    "    The work for a single thread.\n",
    "    # todo\n",
    "    \"\"\"\n",
    "    thread_count[0] += 1\n",
    "    for page in pages:\n",
    "        url = base + str(page)\n",
    "        req = requests.get(url)\n",
    "        bs = BeautifulSoup(req.text, features='html.parser')\n",
    "        tds = bs.find_all('td', class_='views-field-pw-version-title')\n",
    "        if tds is None:\n",
    "            failed_page_idx.append(page)\n",
    "        for td in tds:\n",
    "            a = td.find('a')\n",
    "            href = a.get('href')\n",
    "            title = a.text.strip()\n",
    "            api_links[href] = title\n",
    "    \n",
    "    thread_count[0] -= 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "RI_ufZyLa1mH",
    "tags": []
   },
   "outputs": [],
   "source": [
    "max_thread = 40\n",
    "thread_count = [0]\n",
    "\n",
    "# page = 0\n",
    "# A simple but unsafe way to use multi-threads\n",
    "i = 0\n",
    "length = len(pages_split)\n",
    "while True:\n",
    "    if i >= length:\n",
    "        break\n",
    "    if thread_count[0] < max_thread:\n",
    "        # For each thread, get all API detail links in a page.\n",
    "        t = threading.Thread(target=get_list, args=(thread_count, pages_split[i]))\n",
    "        t.start()\n",
    "        print('Created a new thread. Processing the ', (i + 1), 'th sublist. There are ', length, 'sublists in all.')\n",
    "        i += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 34
    },
    "id": "vskl-ejmXd2D",
    "outputId": "476c89de-8a1d-42fe-ac81-6a27327533a6"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "23676"
      ]
     },
     "execution_count": 5,
     "metadata": {
      "tags": []
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(api_links)  # preview"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "YT0sZwqnuk2l"
   },
   "outputs": [],
   "source": [
    "# Save the links to a text file\n",
    "with open('api_links0909-1.txt', 'w', encoding='utf-8') as file:\n",
    "    for link in api_links:\n",
    "        file.write(link + '\\n')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "ZP_eMTgvTxCG"
   },
   "outputs": [],
   "source": [
    "# Get the detail information of an API\n",
    "def get_api(url, is_dead_api=False):\n",
    "    req_api = requests.get('https://www.programmableweb.com' + url)\n",
    "    bs_api = BeautifulSoup(req_api.text, features='html.parser')\n",
    "    # 找node-header，锁定标题\n",
    "    node_header = bs_api.find('div', class_='node-header')\n",
    "    if node_header is None:\n",
    "        # 失败\n",
    "        failed_api_hrefs.append(url)\n",
    "        print('failed')\n",
    "        return None\n",
    "    title = node_header.find('h1').text.strip()     # title\n",
    "\n",
    "    tags = []   #tags\n",
    "    div_tags = bs_api.find('div', class_='tags')\n",
    "    tags_a = div_tags.find_all('a')\n",
    "    for a in tags_a:\n",
    "        tags.append(a.text.strip())\n",
    "\n",
    "    intro = bs_api.find('div', class_='intro')\n",
    "    description = ''\n",
    "    if intro is None:\n",
    "        # 失败\n",
    "        failed_api_hrefs.append(url)\n",
    "        print('not found intro')\n",
    "    else:\n",
    "        description_div = intro.find('div', class_='api_description')\n",
    "        if description_div is None:\n",
    "            # failed_api_hrefs.append(url)\n",
    "            print('not found description_div')\n",
    "        else:\n",
    "            description = description_div.text.strip()  #description\n",
    "\n",
    "    # 定位版本versions\n",
    "    versions = []\n",
    "    version_field = bs_api.find('div', id='version-details-field')\n",
    "    version_results = version_field.find_all('div', class_='version-result-set')\n",
    "    \n",
    "    # 开始获取版本\n",
    "    for result in version_results:\n",
    "        divs = result.find_all('div')\n",
    "        version_title = ''\n",
    "        version_style = ''\n",
    "        version_status = ''\n",
    "        version_version = ''\n",
    "        version_submit_date = ''\n",
    "        version_link = ''\n",
    "        for div in divs:\n",
    "            # 直接找所有div，根据label去匹配\n",
    "            label = div.find('label')\n",
    "            if label is None:\n",
    "                # 不是我要的div\n",
    "                continue\n",
    "            else:\n",
    "                lt = label.text.strip()\n",
    "                version_info = div.text.strip()\n",
    "                if lt == 'Title:':\n",
    "                    version_title = version_info.split(':')[1]\n",
    "                    # 寻找a标签\n",
    "                    version_a = div.find('a')\n",
    "                    if version_a is None:\n",
    "                        print('not found a tag of this version')\n",
    "                        version_link = 'not found'\n",
    "                    else:\n",
    "                        version_link = version_a.get('href')\n",
    "                elif lt == 'Style:':\n",
    "                    version_style = version_info.split(':')[1]\n",
    "                elif lt == 'Version:':\n",
    "                    version_version = version_info.split(':')[1]\n",
    "                elif lt == 'Status:':\n",
    "                    # 这个没发现什么好的办法，直接取得所有span\n",
    "                    spans = div.find_all('span')\n",
    "                    # 因为0是那个mobile，我不需要，只需要1\n",
    "                    span = spans[1]\n",
    "                    version_status = span.text.strip()\n",
    "                elif lt == 'Submitted:':\n",
    "                    version_submit_date = version_info.split(':')[1]\n",
    "        version = ApiVersion(version_title, version_style, version_status, version_version, version_submit_date, version_link)\n",
    "        versions.append(version)\n",
    "\n",
    "    # 创建API对象\n",
    "    if is_dead_api:\n",
    "        # 是已经dead的API，获得他的changelog，以推算API的死亡日期\n",
    "        # 获得changelogs\n",
    "        changelogs = get_changelogs(url)\n",
    "        deprecated_date = 'Not sure'\n",
    "        if len(changelogs) == 1:\n",
    "            deprecated_date = changelogs[0].split('|')[0]\n",
    "        api = DeadPoolApi(title, tags, description, url, versions, changelogs, deprecated_date)\n",
    "    else:\n",
    "        api = Api(title, tags, description, url, versions)\n",
    "    # apis[url] = api\n",
    "    # print(api.title)\n",
    "    return api\n",
    "\n",
    "def threads_get_api(thread_count, api_list):\n",
    "    thread_count[0] += 1\n",
    "    for url in api_list:\n",
    "        api = get_api(url)\n",
    "        apis.append(api)\n",
    "    thread_count[0] -= 1\n",
    "\n",
    "def threads_get_dead_api(thread_count, api_list):\n",
    "    thread_count[0] += 1\n",
    "    for url in api_list:\n",
    "        api = get_api(url, is_dead_api=True)\n",
    "        apis.append(api)\n",
    "    thread_count[0] -= 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "DnZjSQJh0CdW"
   },
   "outputs": [],
   "source": [
    "# 9.9 爬取deadpool的补充，因为需要爬changelog才有可能确定\n",
    "# 现在做两件事：\n",
    "# 1. 爬取API的changelog，有可能会写出\"deadpool\"，然后获取这个log的日期\n",
    "# 2. 爬取API的各个已经不活跃的version的changelog，有可能出现\"deactiveted\"\n",
    "# changelog_map = {}\n",
    "def get_changelogs(url):\n",
    "    changelogs = []\n",
    "    change_req = requests.get('https://www.programmableweb.com' + url + '/changelog')\n",
    "    cbs = BeautifulSoup(change_req.text, features='html.parser')    # changelog beautiful soup\n",
    "    changelog_divs = cbs.find_all('p', class_='changelog_divider')\n",
    "    for changelog_div in changelog_divs:\n",
    "        changelog_text = changelog_div.get_text(\"|\", strip=True)\n",
    "        if 'deadpool' in changelog_text.lower():\n",
    "            print(True)\n",
    "            # 有用的changelog\n",
    "            changelogs.append(changelog_text)\n",
    "    return changelogs\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 236
    },
    "id": "SuBmFOQGT-Kh",
    "outputId": "032c4328-f389-41a1-ec5f-1dd565bccb77"
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "ignored",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-36-71866decf479>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mapi_list\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mapi_links\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mkeys\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[0;31m# api_list1 = api_list[:5000]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[0;31m# api_list2 = api_list[5000:10000]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0;31m# api_list3 = api_list[10000:15000]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mNameError\u001b[0m: name 'api_links' is not defined"
     ]
    }
   ],
   "source": [
    "api_list = list(api_links.keys())\n",
    "\n",
    "api_list1 = api_list[:5000]\n",
    "api_list2 = api_list[5000:10000]\n",
    "api_list3 = api_list[10000:15000]\n",
    "api_list4 = api_list[15000:20000]\n",
    "api_list5 = api_list[20000:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "7P0ItP_UAAz0"
   },
   "outputs": [],
   "source": [
    "# 写文件\n",
    "with open('file5.txt', 'w', encoding='utf-8') as file2:\n",
    "    for aaa in api_list5:\n",
    "        file2.write(aaa + '\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "g8AyAzMmV0Tj"
   },
   "outputs": [],
   "source": [
    "# 读文件\n",
    "api_list3 = []\n",
    "with open('file3.txt', 'r', encoding='utf-8') as file:\n",
    "    for line in file:\n",
    "        api_list3.append(line)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "pNgowV6d2tXD"
   },
   "outputs": [],
   "source": [
    "# api_lists = [api_list1, api_list2, api_list3, api_list4, api_list5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "hdUyqOW677VA"
   },
   "outputs": [],
   "source": [
    "# load the five files\n",
    "api_lists = []\n",
    "i = 0\n",
    "for i in range(1, 6):\n",
    "    temp_list = []\n",
    "    with open('file' + str(i) + '.txt', 'r', encoding='utf-8') as file:\n",
    "        for line in file:\n",
    "            temp_list.append(line)\n",
    "    api_lists.append(temp_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 34
    },
    "id": "lEFztM5S3Wu8",
    "outputId": "56e21cdf-7da1-4f56-f88b-94802ddc98de"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 9,
     "metadata": {
      "tags": []
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "splits = []\n",
    "for al in api_lists:\n",
    "    splits.append(list_split(al, 12))\n",
    "len(splits)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "206PfiKU4ZUD"
   },
   "outputs": [],
   "source": [
    "max_thread = 80\n",
    "thread_count = [0]\n",
    "\n",
    "apis = []   \n",
    "failed_api_hrefs = []   # empty the failed links\n",
    "threads = []\n",
    "\n",
    "for idx in range(len(splits)):  # idx file index. 0~4(5 files in all)\n",
    "    # better to run the code below manually for 5 times.\n",
    "    now_list = splits[idx]\n",
    "    i = 0\n",
    "    length = len(now_list)\n",
    "    thread_count[0] = 0\n",
    "    while True:\n",
    "        if i >= length:\n",
    "            break\n",
    "        if thread_count[0] <= max_thread:\n",
    "            t = threading.Thread(target=threads_get_api, args=(thread_count, now_list[i]))\n",
    "            threads.append(t)\n",
    "            t.start()\n",
    "            print('Created a new thread. Processing the ', (i + 1), 'th sublist. There are', length, 'sublists in all')\n",
    "            i += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 751
    },
    "id": "A-8QE6OMeitB",
    "outputId": "3f5a95dd-6bbd-43a4-d25e-d31b2dbfb6b0"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[\n",
      "  {\n",
      "    \"title\": \"Dextro Image Recognition API MASTER RECORD\",\n",
      "    \"tags\": [\n",
      "      \"Photos\",\n",
      "      \"Recognition\"\n",
      "    ],\n",
      "    \"description\": \"Dextro Image Recognition is a service that allows for object recognition in images. Dextro's functionality recognizes objects and the location of objects in images.\\nThe Dextro Image Recognition API allows developers to access and integrate the functionality of Dextro with other applications. Public documentation is not available; interested developers should sign up here for API access: https://www.dextrorobotics.com/signup.\",\n",
      "    \"url\": \"/api/dextro-image-recognition\\n\",\n",
      "    \"versions\": [\n",
      "      {\n",
      "        \"version_title\": \"Dextro Image Recognition REST API\",\n",
      "        \"style\": \"REST\",\n",
      "        \"version\": \"Recommended (active, supported)\",\n",
      "        \"status\": \"N/A\",\n",
      "        \"submit_date\": \"01.15.2013\",\n",
      "        \"version_link\": \"/api/dextro-image-recognition-rest-api\"\n",
      "      }\n",
      "    ]\n",
      "  },\n",
      "  {\n",
      "    \"title\": \"BriteVerify API MASTER RECORD\",\n",
      "    \"tags\": [\n",
      "      \"Email\",\n",
      "      \"Real Time\",\n",
      "      \"Security\",\n",
      "      \"Verification\"\n",
      "    ],\n",
      "    \"description\": \"BriteVerify is an email data verification platform that connects with email domains to perform real time account status verification of email addresses. The API allows developers to integrate the system backend with 3rd party applications. The data elements available for verification are: Name, Email, Postal Address, Phone, IP Address. The API uses RESTful calls and responses are formatted in XML and JSON.\",\n",
      "    \"url\": \"/api/briteverify\\n\",\n",
      "    \"versions\": [\n",
      "      {\n",
      "        \"version_title\": \"BriteVerify REST API\",\n",
      "        \"style\": \"REST\",\n",
      "        \"version\": \"Recommended (active, supported)\",\n",
      "        \"status\": \"N/A\",\n",
      "        \"submit_date\": \"07.06.2011\",\n",
      "        \"version_link\": \"/api/briteverify-rest-api\"\n",
      "      }\n",
      "    ]\n",
      "  }\n",
      "]\n"
     ]
    }
   ],
   "source": [
    "# preview\n",
    "print(json.dumps(obj=apis[:2], default=lambda x : x.__dict__, sort_keys=False, indent=2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "czUKEy7A6XUi"
   },
   "outputs": [],
   "source": [
    "# 成功的列表写入文件\n",
    "with open('apilist5-0915-1.txt', 'w', encoding='utf-8') as file1:\n",
    "    file1.write(json.dumps(obj=apis, default=lambda x : x.__dict__, sort_keys=False, indent=2))   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "wRtCIusZkifA"
   },
   "outputs": [],
   "source": [
    "# 失败的列表（全是链接）写入文件\n",
    "with open('failedapilist5-0915-1.txt', 'w', encoding='utf-8') as file1:\n",
    "    for href in failed_api_hrefs:\n",
    "        file1.write(href)   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 71
    },
    "id": "Ke8FHAdwJy3I",
    "outputId": "caf49655-910f-4d98-fdb1-8cc1aa3c1c3d"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "105\n",
      "['/api/google-url-shortener\\n', '/api/aonaware-dictionary\\n', '/api/salesforce\\n', '/api/change-healthcare\\n', '/api/joinesty\\n', '/api/musicmobs\\n', '/api/strain\\n', '/api/us-yellow-pages\\n', '/api/winecom\\n', '/api/windows-live-gadgets\\n']\n"
     ]
    }
   ],
   "source": [
    "# 最后爬一下失败的链接\n",
    "failed_hrefs = []\n",
    "with open('failedapilist1-5.txt', 'r', encoding='utf-8') as failed:\n",
    "    for line in failed:\n",
    "        failed_hrefs.append(line)\n",
    "\n",
    "# preview\n",
    "print(len(failed_hrefs))    # need to be re-crawled\n",
    "print(failed_hrefs[:10])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "CQzDUVZVLfEx"
   },
   "source": [
    "# New requirements - Accessibility\n",
    "\n",
    "- Acccess to the Endpoint Address to recognize whether the API is still accessible\n",
    "- Save the status code/accessibility\n",
    "- The Endpoint Address appears in each version's link, so I have to access to every version's URL\n",
    "- Test the versions marked as Active. For those versions which are alreay deactivated will not be tested. \n",
    "\n",
    "## How to decide an API's accessibility\n",
    "- By its versions data\n",
    "    1. For all versions in one API, and look up the status provided by ProgrammableWeb.\n",
    "    2. If all versions are marked as deactivated, this API is a dead API. If not(at least one version is active), it will be marked as active, and further tests will be done.\n",
    "- Further tests: access to its website\n",
    "    1. For all active APIs's versions, access to their Endpoing Address.\n",
    "    2. If none of the websites is accessible, the API will be marked as deactivated, else active.\n",
    "\n",
    "------\n",
    "\n",
    "Note: NOT deactived. IT'S deactivated"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "AUSa5gWUKTSc"
   },
   "outputs": [],
   "source": [
    "# Load the API dataset.\n",
    "with open('apis0915.txt', 'r', encoding='utf-8') as file:\n",
    "    apis_list = json.loads(text)\n",
    "    apis_list = [at for at in apis_list if at is not None]\n",
    "\n",
    "apis_list[:5]   # preview"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "RKD6ZhECoIWV"
   },
   "outputs": [],
   "source": [
    "# Note: This cell is used to filter the APIs which are marked as active in ProgrammableWeb\n",
    "# These active APIs need to be tested more in the below cells.\n",
    "\n",
    "apis = []\n",
    "all_versions = []   # 存储不管是什么API的version，最后用到它的长度\n",
    "active_apis = []    # 标记为活跃的API\n",
    "deactive_apis = []      # 标记为不活跃的API （所有version都是deactivate）\n",
    "for api in apis_list:\n",
    "    versions = []\n",
    "    is_active_api = False   # 后面遍历所有version，如果全部都是deactivate的，那么这个标记就是False\n",
    "    for version in api['versions']:\n",
    "        api_version = ApiVersion('', '', '', '', '', '')\n",
    "        api_version.__dict__ = version\n",
    "        versions.append(api_version)\n",
    "        all_versions.append(api_version)\n",
    "        if api_version.version is not 'Deactivated':\n",
    "            is_active_api = True\n",
    "\n",
    "    aaa = Api(api['title'], api['tags'], api['description'], api['url'], versions)\n",
    "    apis.append(aaa)\n",
    "    if is_active_api:\n",
    "        active_apis.append(aaa)\n",
    "    else:\n",
    "        deactive_apis.append(aaa)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 104
    },
    "id": "1M74t2O80LI-",
    "outputId": "7f01a4d9-ecda-4f2a-954c-24994700e595"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "All apis: 21569\n",
      "All versions: 22207\n",
      "Active apis: 21566\n",
      "Deactive apis: 3\n"
     ]
    }
   ],
   "source": [
    "# 看看数量\n",
    "print('All apis:', len(apis))\n",
    "print('All versions:', len(all_versions))\n",
    "print('Active apis:', len(active_apis))\n",
    "print('Deactive apis:', len(deactive_apis))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "eDe3mKouKTSf",
    "tags": []
   },
   "outputs": [],
   "source": [
    "print(apis[0].json())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "paAty34kKTSg"
   },
   "outputs": [],
   "source": [
    "actived_versions = {}\n",
    "a_apis = []\n",
    "# version_title->Api\n",
    "i = 0\n",
    "for api_dict in apis:\n",
    "    # 选出非deactived的api和他的version\n",
    "    a_apis.append(api_dict)\n",
    "    versions = api_dict['versions']\n",
    "    for version in versions:\n",
    "        if version['version'] is not 'Deactivated':\n",
    "            actived_versions[version['version_title']] = api_dict\n",
    "    i += 1    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 74
    },
    "id": "RNLZlHxiKTSj",
    "outputId": "e9871841-2ed6-4f8b-bd84-513ad8e7a3e2"
   },
   "outputs": [
    {
     "data": {
      "application/vnd.google.colaboratory.intrinsic+json": {
       "type": "string"
      },
      "text/plain": [
       "'{\\n  \"version_title\": \"Envato REST API\",\\n  \"style\": \"REST\",\\n  \"version\": \"Recommended (active, supported)\",\\n  \"status\": \"N/A\",\\n  \"submit_date\": \"03.02.2011\",\\n  \"version_link\": \"/api/envato-rest-api\"\\n}'"
      ]
     },
     "execution_count": 66,
     "metadata": {
      "tags": []
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "keys = list(actived_versions.keys())    # keys 就是title列表\n",
    "keys[0].json()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "from data.crawler.data_objects import SimplifiedApi, VersionVisit, VisitStatus"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "Ukaqb5QGN9ID"
   },
   "outputs": [],
   "source": [
    "# 定义多线程爬取versions的方法\n",
    "# 部分API可以按照把版本的名字中的空格修改为短横线作为URL\n",
    "base_url = 'https://www.programmableweb.com'\n",
    "def get_version(version):\n",
    "    # 制作URL\n",
    "    url = base_url + version.version_link\n",
    "    req = requests.get(url)\n",
    "\n",
    "    version_title = version.version_title\n",
    "    version_url = url\n",
    "    visit_status = []\n",
    "    is_accessible = False\n",
    "\n",
    "    from_api_dict = actived_versions[version]\n",
    "    api_title = from_api_dict.title\n",
    "    api_url = from_api_dict.url\n",
    "    from_api = SimplifiedApi(api_title, api_url)\n",
    "    is_endpoint_accessbile = 'Undefined'\n",
    "    is_homepage_accessible = 'Undefined'\n",
    "\n",
    "    if req.status_code == requests.codes.ok:\n",
    "        # 成功的\n",
    "        # 爬取里面的各种a标签\n",
    "        bs = BeautifulSoup(req.text, features='html.parser')\n",
    "        specs = bs.find('div', class_='section specs')\n",
    "        if specs is None:\n",
    "            cannot_find_html_element.append(url)\n",
    "        else:\n",
    "            # 找到了spec的列表\n",
    "            # 获取所有a标签\n",
    "            a_tags = specs.find_all('a')\n",
    "            for a_tag in a_tags:\n",
    "                # 遍历所有a标签，然后找他们的父节点，找到label\n",
    "                # 然后访问这个a标签，记录下访问状态\n",
    "                label = a_tag.parent.parent.find('label')\n",
    "                if label is None:\n",
    "                    print('not found label. URL:', url)\n",
    "                    label_text = 'Undefined'\n",
    "                else:\n",
    "                    label_text = label.text.strip()\n",
    "                a_href = a_tag.get('href')\n",
    "                if 'http' not in a_href:\n",
    "                    # 这个href就不访问了，因为是站内的\n",
    "                    continue\n",
    "\n",
    "                visit_url = a_href\n",
    "                visit_label = label_text\n",
    "                status_code = 0\n",
    "\n",
    "                # 访问a标签\n",
    "                try:\n",
    "                    a_req = requests.get(a_href)\n",
    "                    status_code = a_req.status_code\n",
    "                except:\n",
    "                    status_code = -1\n",
    "\n",
    "                # 这里仅利用 end point 去判断 is accessible or not\n",
    "                if label_text == 'API Endpoint':\n",
    "                    if status_code == 200 or status_code == 429:\n",
    "                        # 只有200才标记为True，否则都是False\n",
    "                        is_accessible = True    # tag it as accessible\n",
    "                        is_endpoint_accessbile = True\n",
    "                    else:\n",
    "                        is_endpoint_accessbile = False\n",
    "                elif 'Portal' in label_text:\n",
    "                    if status_code == 200 or status_code == 429:\n",
    "                        # 只有200才标记为True，否则都是False\n",
    "                        is_homepage_accessible = True\n",
    "                    else:\n",
    "                        is_homepage_accessible = False\n",
    "\n",
    "                \n",
    "                status = VisitStatus(visit_url, visit_label, status_code)\n",
    "                visit_status.append(status)\n",
    "        a_visit = VersionVisit(version_title, version_url, from_api, visit_status, is_accessible, is_endpoint_accessbile, is_homepage_accessible)\n",
    "        # version_visits.append(a_visit)\n",
    "        visited_url.append(version_url)\n",
    "        return a_visit\n",
    "    else:\n",
    "        # 不知道是什么原因失败了，但是很可能是404\n",
    "        failed_version_url.append(url)\n",
    "        print('failed', url)\n",
    "\n",
    "\n",
    "# The work for each thread\n",
    "def threads_get_version_visit(thread_count, version_list):\n",
    "    thread_count[0] += 1\n",
    "    for version in version_list:\n",
    "        a_visit = get_version(version)    # 获取一次访问结果\n",
    "        # 判断是否为None\n",
    "        if a_visit is not None:\n",
    "            version_visits.append(a_visit)\n",
    "    thread_count[0] -= 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 54
    },
    "id": "r78_x-nEQypr",
    "outputId": "a7009a1c-e606-4953-bab6-64cbec6194b6"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "625\n"
     ]
    }
   ],
   "source": [
    "# len(keys)   # 22239\n",
    "# 分割列表\n",
    "splits_temp = list_split(keys, 5000)\n",
    "splits = []\n",
    "for list_ in splits_temp:\n",
    "    splits.append(list_split(list_, 8))\n",
    "print(len(splits[0]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "wyqXlqeXKTSm",
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Similar to crawling the API details\n",
    "failed_version_url = []\n",
    "cannot_find_html_element = []\n",
    "version_visits = []\n",
    "available_status = [200, 429]\n",
    "visited_url = []\n",
    "# 多线程爬取\n",
    "max_thread = 60\n",
    "thread_count = [0]\n",
    "\n",
    "# Change this idx number to access to different sublist at different time to prevent ip being banned\n",
    "# When finished one sublist, save as a text file\n",
    "idx = 4\n",
    "now_list = splits[idx]\n",
    "i = 0\n",
    "length = len(now_list)\n",
    "while True:\n",
    "    if i >= length:\n",
    "        break\n",
    "    if thread_count[0] <= max_thread:\n",
    "        t = threading.Thread(target=threads_get_version_visit, args=(thread_count, now_list[i]))\n",
    "        t.start()\n",
    "        print('Created a new thread. Processing the ', (i + 1), 'th sublist. There are', length, 'sublists in all')\n",
    "        i += 1\n",
    "\n",
    "# ensure the list of failed links is empty\n",
    "# ensure the list of failed links is empty\n",
    "# ensure the list of failed links is empty\n",
    "\n",
    "# preivew\n",
    "print(json.dumps(obj=version_visits[:10], default=lambda x : x.__dict__, sort_keys=False, indent=2))\n",
    "\n",
    "# save to file\n",
    "with open('version_status0915-5.txt', 'w', encoding='utf-8') as file:\n",
    "    # json.dump is better\n",
    "    file.write(json.dumps(obj=version_visits, default=lambda x : x.__dict__, sort_keys=False, indent=2))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 54
    },
    "id": "Z6rj6JaJc1VH",
    "outputId": "e9364dbb-f4f0-4ccd-e088-46d2138b241a"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.536330608537693\n"
     ]
    }
   ],
   "source": [
    "# accessible versions ratio\n",
    "accessible = 0\n",
    "for vis in version_visits:\n",
    "    for status in vis.visit_status:\n",
    "        if status.visit_label == 'API Portal / Home Page':\n",
    "            if status.status_code == 200 or status.status_code == 429:\n",
    "                accessible += 1\n",
    "            break\n",
    "print(float(accessible) / len(version_visits))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "cgWUaX2mofpW"
   },
   "source": [
    "# Trying visualization\n",
    "\n",
    "分成多个图\n",
    "- 按照version绘图，表示出标记正确的version和标记错误的version以及占比\n",
    "- 按照API绘图，以API的链接作为区分，表示出正确和错误的占比\n",
    "- 分别以可否访问endpoint 和 portal/homepage 作为API是否存活的依据，绘制上面两个图"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "c7osoLV3dMEn"
   },
   "outputs": [],
   "source": [
    "from matplotlib import pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 120
    },
    "id": "H79b91XIocqL",
    "outputId": "bd15c786-6de4-4363-bcf8-748f616b3138"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6175036\n",
      "5673184\n",
      "5142386\n",
      "4539876\n",
      "1916781\n"
     ]
    }
   ],
   "source": [
    "# 读取version_status 文件\n",
    "version_visits = []\n",
    "for i in range(1, 6):\n",
    "    text = ''\n",
    "    with open('version_status0915-' + str(i) + '.txt', 'r', encoding='utf-8') as file:\n",
    "        text = file.read()\n",
    "    # json 解析\n",
    "    version_visits_dicts = json.loads(text)\n",
    "\n",
    "    for visit_dict in version_visits_dicts:\n",
    "        from_api_dict = visit_dict['from_api']\n",
    "        from_api = SimplifiedApi(from_api_dict['api_title'], from_api_dict['url'])\n",
    "        visit_status_list = []\n",
    "        for status in visit_dict['visit_status']:\n",
    "            visit_status_list.append(VisitStatus(status['visit_url'], status['visit_label'], status['status_code']))\n",
    "        version_visits.append(VersionVisit(visit_dict['version_title'], visit_dict['version_url'], from_api, visit_status_list, visit_dict['is_accessible'], visit_dict['is_endpoint_accessbile'], visit_dict['is_homepage_accessible']))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 54
    },
    "id": "HpTm3JdgodGc",
    "outputId": "0c9114f6-d85c-463b-de4f-e31ff2072bed"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "22055"
      ]
     },
     "execution_count": 20,
     "metadata": {
      "tags": []
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(version_visits)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "AwYepSRewi-a"
   },
   "outputs": [],
   "source": [
    "def is_active_api(api_link):\n",
    "    for api in active_apis:\n",
    "        if api.url == api_link:\n",
    "            return True\n",
    "    return False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "L2NQ9qpIolDx"
   },
   "outputs": [],
   "source": [
    "def show_pie(version_visits):\n",
    "    # 分成四个图\n",
    "    # 先统计\n",
    "    # 1. 按照 endpoint 统计\n",
    "    # 2. 按照 portal 统计\n",
    "    apis = set()\n",
    "    endpoint_accessible_versions = []\n",
    "    endpoint_accessible_apis = set()\n",
    "    homepage_accessible_versions = []\n",
    "    homepage_accessible_apis = set()\n",
    "    for visit in version_visits:\n",
    "        # 如果是对象\n",
    "        from_api_url = visit.from_api.url.strip()\n",
    "        apis.add(from_api_url)\n",
    "\n",
    "        for status in visit.visit_status:\n",
    "            if status.visit_label == 'API Endpoint':\n",
    "                if status.status_code == 200 or status.status_code == 429:\n",
    "                    endpoint_accessible_versions.append(visit)\n",
    "                    endpoint_accessible_apis.add(from_api_url)      # 这就保证了只要有一个version是可访问的，这个API就作为可访问的\n",
    "            elif status.visit_label == 'API Portal / Home Page':\n",
    "                if status.status_code == 200 or status.status_code == 429:\n",
    "                    homepage_accessible_versions.append(visit)\n",
    "                    homepage_accessible_apis.add(from_api_url)\n",
    "\n",
    "    # 统计完了\n",
    "\n",
    "    # 绘图\n",
    "    version_length = len(version_visits)\n",
    "    api_length = len(apis) + 1951\n",
    "\n",
    "    plt.suptitle(\"Active versions' accessibility\")\n",
    "    p1 = plt.subplot(1, 2, 1)\n",
    "    plt.title('API Endpoint')\n",
    "    endpoint_length = len(endpoint_accessible_versions)\n",
    "    plt.pie(x=[endpoint_length, version_length - endpoint_length], labels=['Accessible', 'Inaccessible'], autopct='%.2f%%')\n",
    "\n",
    "    p2 = plt.subplot(1, 2, 2)\n",
    "    plt.title('API Portal / Home Page')\n",
    "    homepage_length = len(homepage_accessible_versions)\n",
    "    plt.pie(x=[homepage_length, version_length - homepage_length], labels=['Accessible', 'Inaccessible'], autopct='%.2f%%')\n",
    "    plt.show()\n",
    "\n",
    "    plt.suptitle(\"Active APIs' accessibility\")\n",
    "    p3 = plt.subplot(1, 2, 1)\n",
    "    plt.title('API Endpoint')\n",
    "    endpoint_api_length = len(endpoint_accessible_apis)\n",
    "    plt.pie(x=[endpoint_api_length, api_length - endpoint_api_length], labels=['Accessible', 'Inaccessible'], autopct='%.2f%%')\n",
    "\n",
    "    p4 = plt.subplot(1, 2, 2)\n",
    "    plt.title('API Portal / Home Page')\n",
    "    homepage_api_length = len(homepage_accessible_apis)\n",
    "    plt.pie(x=[homepage_api_length, api_length - homepage_api_length], labels=['Accessible', 'Inaccessible'], autopct='%.2f%%')\n",
    "    plt.show()\n",
    "\n",
    "    print('Judged by API Endpoint, ' + str(endpoint_api_length) + ' of ' + str(api_length) + ' in all are active')\n",
    "    print('Judged by API Homepage, ' + str(homepage_api_length) + ' of ' + str(api_length) + ' in all are active')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 526
    },
    "id": "iociP3o3uhC7",
    "outputId": "dbdf3faa-6b24-4fb7-c7fd-4363fc66a5ef"
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "tags": []
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "tags": []
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Judged by API Endpoint, 5185 of 23385 in all are active\n",
      "Judged by API Homepage, 14283 of 23385 in all are active\n"
     ]
    }
   ],
   "source": [
    "show_pie(version_visits)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "fcs4dB5zvED8"
   },
   "outputs": [],
   "source": [
    "\n"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [],
   "name": "Api_Grabber.ipynb",
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
